home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 6 code / TCP / NewsWatcher / NW Source / Shared Code / Reusable Source / strutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-27  |  10.7 KB  |  397 lines  |  [TEXT/MMCC]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     strutil.c
  4.  
  5.     This reusable module contains miscellaneous string handling 
  6.     utility routines.
  7.     
  8.     Copyright © 1994-1995, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include "def.h"
  16. #include "strutil.h"
  17. #include "memutil.h"
  18.  
  19.  
  20.  
  21. /* This table maps characters together for a case and diacritical 
  22.    insensitive comparison, using the Mac 8 bit international character set. */
  23.  
  24. static unsigned char gTable[256] = {
  25.     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
  26.     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
  27.     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
  28.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  29.     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
  30.     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
  31.     0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
  32.     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
  33.     0x41, 0x41, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45,
  34.     0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55,
  35.     0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0x4F,
  36.     0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xAE, 0x4F,
  37.     0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0x22, 0x22, 0xC9, 0x20, 0x41, 0x41, 0x4F, 0xAE, 0xAE,
  38.     0xD0, 0xD1, 0x22, 0x22, 0x27, 0x27, 0xD6, 0xD7, 0x59, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
  39.     0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
  40.     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
  41. };
  42.  
  43.  
  44.  
  45. /*----------------------------------------------------------------------------
  46.     MyStrCmp 
  47.     
  48.     Compare two strings, case and diacritical insensitive.
  49.             
  50.     Entry:    s1 = pointer to first C-format string.
  51.             s2 = pointer to second C-format string.
  52.             
  53.     Exit:    function result = 
  54.                 -1 if s1 < s2.
  55.                  0 if s1 = s2.
  56.                 +1 if s1 > s2.
  57. ----------------------------------------------------------------------------*/
  58.  
  59. short MyStrCmp (char *s1, char *s2)
  60. {
  61.     unsigned char *t = gTable;
  62.     unsigned char *us1 = (unsigned char*)s1;
  63.     unsigned char *us2 = (unsigned char*)s2;
  64.  
  65.     while (t[*us1] == t[*us2]) {
  66.         if (*us1++ == 0) return 0;
  67.         us2++;
  68.     }
  69.     return t[*us1] < t[*us2] ? -1 : +1;
  70. }
  71.  
  72.  
  73.  
  74. /*----------------------------------------------------------------------------
  75.     MyStrEqual 
  76.     
  77.     Compare two strings, case and diacritical insensitive.
  78.             
  79.     Entry:    s1 = pointer to first C-format string.
  80.             s2 = pointer to second C-format string.
  81.             
  82.     Exit:    function result = true if strings are equal.
  83. ----------------------------------------------------------------------------*/
  84.  
  85. Boolean MyStrEqual (char *s1, char *s2)
  86. {
  87.     unsigned char *t = gTable;
  88.     unsigned char *us1 = (unsigned char*)s1;
  89.     unsigned char *us2 = (unsigned char*)s2;
  90.  
  91.     while (t[*us1] == t[*us2++])
  92.         if (*us1++ == 0) return true;
  93.     return false;
  94. }
  95.  
  96.  
  97.  
  98. /*----------------------------------------------------------------------------
  99.     MyStrNEqual 
  100.     
  101.     Compare the first n characters of two strings, case and diacritical 
  102.     insensitive.
  103.             
  104.     Entry:    s1 = pointer to first string.
  105.             s2 = pointer to second string.
  106.             n = number of characters to compare.
  107.             
  108.     Exit:    function result = true if equal.
  109. ----------------------------------------------------------------------------*/
  110.  
  111. Boolean MyStrNEqual (char *s1, char *s2, short n)
  112. {
  113.     unsigned char *t = gTable;
  114.     unsigned char *us1 = (unsigned char *)s1;
  115.     unsigned char *us2 = (unsigned char *)s2;
  116.  
  117.     while (--n >= 0 && t[*us1++] == t[*us2++]) /* do nothing */;
  118.     return n < 0;
  119. }
  120.  
  121.  
  122.  
  123. /*----------------------------------------------------------------------------
  124.     MyNSubstringSearch 
  125.     
  126.     Do a case and diacritical insensitive substring search.
  127.             
  128.     Entry:    s1 = pointer to string to be searched.
  129.             s2 = pointer to search string, C-format.
  130.             s1len = length of s1.
  131.             giveTime = pointer to give time function, or nil if none.
  132.             
  133.     Exit:    function result = error code = userCanceledErr if
  134.                 giveTime != nil and search canceled by user, else
  135.                 noErr.
  136.             *offset = offset in s1 of first occurence of s2, or
  137.                 -1 if none found.
  138. ----------------------------------------------------------------------------*/
  139.  
  140. OSErr MyNSubstringSearch (char *s1, char *s2, long s1len, long *offset,
  141.     OSErr (*giveTime)(Boolean))
  142. {
  143.     unsigned char *t = gTable;
  144.     unsigned char *p, *q, *s1Start;
  145.     long n;
  146.     unsigned long tickLongTime;
  147.     Boolean longTime = false;
  148.     OSErr err = noErr;
  149.  
  150.     if (*s2 == 0) {
  151.         *offset = 0;
  152.         return noErr;
  153.     }
  154.     n = s1len - strlen(s2) + 1;
  155.     s1Start = (unsigned char*)s1;
  156.     tickLongTime = TickCount() + 30;
  157.     while (n-- > 0) {
  158.         p = (unsigned char*)s1;
  159.         q = (unsigned char*)s2;
  160.         while (t[*p] == t[*q]) {
  161.             q++;
  162.             if (*q == 0) {
  163.                 *offset = (unsigned char*)s1 - s1Start;
  164.                 return noErr;
  165.             }
  166.             p++;
  167.         }
  168.         s1++;
  169.         if (giveTime != nil && (n & 0xf) == 0) {
  170.             if (!longTime && TickCount() > tickLongTime) longTime = true;
  171.             if (longTime) {
  172.                 err = (*giveTime)(false);
  173.                 if (err != noErr) return err;
  174.             }
  175.         }
  176.     }
  177.     *offset = -1;
  178.     return noErr;
  179. }
  180.  
  181.  
  182.  
  183. /*----------------------------------------------------------------------------
  184.     MySubstringSearch 
  185.     
  186.     Do a case and diacritical insensitive substring search.
  187.             
  188.     Entry:    s1 = pointer to string to be searched, C-format.
  189.             s2 = pointer to search string, C-format.
  190.             giveTime = pointer to give time function, or nil if none.
  191.             
  192.     Exit:    function result = error code = userCanceledErr if
  193.                 giveTime != nil and search canceled by user, else
  194.                 noErr.
  195.             *offset = offset in s1 of first occurence of s2, or
  196.                 -1 if none found.
  197. ----------------------------------------------------------------------------*/
  198.  
  199. OSErr MySubstringSearch (char *s1, char *s2, long *offset,
  200.     OSErr (*giveTime)(Boolean))
  201. {
  202.     return MyNSubstringSearch (s1, s2, strlen(s1), offset, giveTime);
  203. }
  204.  
  205.  
  206.  
  207. /*----------------------------------------------------------------------------
  208.     MyNIsASubstring 
  209.     
  210.     Do a case and diacritical insensitive substring search.
  211.             
  212.     Entry:    s1 = pointer to string to be searched.
  213.             s2 = pointer to search string, C-format.
  214.             s1len = length of s1.
  215.             
  216.     Exit:    function result = true if s1 contains s2.
  217. ----------------------------------------------------------------------------*/
  218.  
  219. Boolean MyNIsASubstring (char *s1, char *s2, long s1len)
  220. {
  221.     long offset;
  222.  
  223.     MyNSubstringSearch (s1, s2, s1len, &offset, nil);
  224.     return offset != -1;
  225. }
  226.  
  227.  
  228.  
  229. /*----------------------------------------------------------------------------
  230.     MyIsASubstring 
  231.     
  232.     Do a case and diacritical insensitive substring search.
  233.             
  234.     Entry:    s1 = pointer to string to be searched, C-format.
  235.             s2 = pointer to search string, C-format.
  236.             
  237.     Exit:    function result = true if s1 contains s2.
  238. ----------------------------------------------------------------------------*/
  239.  
  240. Boolean MyIsASubstring (char *s1, char *s2)
  241. {
  242.     long offset;
  243.  
  244.     MyNSubstringSearch (s1, s2, strlen(s1), &offset, nil);
  245.     return offset != -1;
  246. }
  247.  
  248.  
  249.  
  250. /*----------------------------------------------------------------------------
  251.     MyIsASubstringHandle
  252.     
  253.     Do a case and diacritical insensitive substring search.
  254.             
  255.     Entry:    h = handle to text to be searched.
  256.             s2 = pointer to search string, C-format.
  257.             
  258.     Exit:    function result = true if s1 contains s2.
  259. ----------------------------------------------------------------------------*/
  260.  
  261. Boolean MyIsASubstringHandle (Handle h, char *s2)
  262. {
  263.     long len, offset;
  264.  
  265.     len = MyGetHandleSize(h);
  266.     MyNSubstringSearch (*h, s2, len, &offset, nil);
  267.     return offset != -1;
  268. }
  269.  
  270.  
  271.  
  272. /*----------------------------------------------------------------------------
  273.     CopyPascalString 
  274.     
  275.     Copy a pascal format string.
  276.             
  277.     Entry:    to = pointer to destination string.
  278.             from = pointer to source string.
  279. ----------------------------------------------------------------------------*/
  280.  
  281. void CopyPascalString (StringPtr to, StringPtr from)
  282. {
  283.     BlockMoveData(from, to, *from+1);
  284. }
  285.  
  286.  
  287.  
  288.  
  289. /*----------------------------------------------------------------------------
  290.     CrackNum 
  291.     
  292.     Crack a decimal number from a string after skipping white space.
  293.     
  294.     Entry:    *x = pointer to string.
  295.             
  296.     Exit:    function result = cracked number.
  297.             *x = pointer to first character following number in string.
  298. ----------------------------------------------------------------------------*/
  299.  
  300. long CrackNum (char **x)
  301. {    
  302.     long result = 0;
  303.     char *y;
  304.     
  305.     y = *x;
  306.     while (isLWSP(*y)) y++;
  307.     while (isdigit(*y)) {
  308.         result = 10*result + (*y - '0');
  309.         y++;
  310.     }
  311.     *x = y;
  312.     return result;
  313. }
  314.  
  315.  
  316.  
  317. /*----------------------------------------------------------------------------
  318.     GetIndCString 
  319.     
  320.     Get a C-format string from an STR# resource.
  321.     
  322.     Entry:    rID = resource id of STR# resource.
  323.             index = index of string in STR# resource.
  324.             
  325.     Exit:    str = string.
  326. ----------------------------------------------------------------------------*/
  327.  
  328. void GetIndCString (char *str, short rID, short index)
  329. {
  330.     GetIndString((StringPtr)str, rID, index);
  331.     p2cstr((StringPtr)str);
  332. }
  333.  
  334.  
  335.  
  336. /*----------------------------------------------------------------------------
  337.     GetCString 
  338.     
  339.     Get a C-format string from the STR# 128 resource.
  340.     
  341.     Entry:    index of string in STR# 128.
  342.             
  343.     Exit:    str = string.
  344. ----------------------------------------------------------------------------*/
  345.  
  346. void GetCString (short index, char *str)
  347. {
  348.     GetIndString((StringPtr)str, 128, index);
  349.     p2cstr((StringPtr)str);
  350. }
  351.  
  352.  
  353.  
  354. /*----------------------------------------------------------------------------
  355.     GetPString 
  356.     
  357.     Get a P-format string from the STR# 128 resource.
  358.     
  359.     Entry:    index of string in STR# 128.
  360.             
  361.     Exit:    str = string.
  362. ----------------------------------------------------------------------------*/
  363.  
  364. void GetPString (short index, StringPtr str)
  365. {
  366.     GetIndString(str, 128, index);
  367. }
  368.  
  369.  
  370.  
  371. /*----------------------------------------------------------------------------
  372.     GetEquivalentCharacters 
  373.     
  374.     Get all characters equivalent to a character under case and diacritical
  375.     insensitive comparison.
  376.     
  377.     Entry:    x = character.
  378.             
  379.     Exit:    equivs = C-format list of equivalent characters.
  380.             *numEquiv = number of equivalent characters.
  381. ----------------------------------------------------------------------------*/
  382.  
  383. void GetEquivalentCharacters (unsigned char x, unsigned char *equivs, short *numEquiv)
  384. {
  385.     unsigned char y;
  386.     unsigned char *p, *q;
  387.     short z;
  388.     
  389.     y = gTable[x];
  390.     q = equivs;
  391.     for (z = 0, p = gTable; z < 256; z++, p++) {
  392.         if (*p == y) *q++ = z;
  393.     }
  394.     *q = 0;
  395.     *numEquiv = q - equivs;
  396. }
  397.